package com.waikuai.shop.controller;

import com.waikuai.shop.common.result.Result;
import com.waikuai.shop.dto.ShippingAddressDTO;
import com.waikuai.shop.service.ShippingAddressService;
import com.waikuai.shop.service.UserService;
import com.waikuai.shop.util.JwtUtil;
import com.waikuai.shop.vo.ShippingAddressVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;

/**
 * 收货地址控制器
 * @author waikuai
 */
@Slf4j
@RestController
@RequestMapping("/addresses")
@RequiredArgsConstructor
@Validated
public class ShippingAddressController {

    private final ShippingAddressService shippingAddressService;
    private final UserService userService;
    private final JwtUtil jwtUtil;

    /**
     * 获取用户收货地址列表
     */
    @GetMapping
    public Result<List<ShippingAddressVO>> getAddressList(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            List<ShippingAddressVO> addresses = shippingAddressService.getUserAddressList(userId);
            
            log.info("获取用户收货地址列表成功，用户ID: {}, 数量: {}", userId, addresses.size());
            return Result.success("获取收货地址列表成功", addresses);
        } catch (Exception e) {
            log.error("获取用户收货地址列表失败: {}", e.getMessage(), e);
            return Result.error("获取收货地址列表失败");
        }
    }

    /**
     * 根据ID获取收货地址
     */
    @GetMapping("/{id}")
    public Result<ShippingAddressVO> getAddress(@PathVariable Long id, HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            ShippingAddressVO address = shippingAddressService.getAddressById(id, userId);
            
            if (address == null) {
                return Result.error("收货地址不存在");
            }
            
            log.info("获取收货地址成功，用户ID: {}, 地址ID: {}", userId, id);
            return Result.success("获取收货地址成功", address);
        } catch (Exception e) {
            log.error("获取收货地址失败: {}", e.getMessage(), e);
            return Result.error("获取收货地址失败");
        }
    }

    /**
     * 新增收货地址
     */
    @PostMapping
    public Result<ShippingAddressVO> addAddress(@Valid @RequestBody ShippingAddressDTO dto,
                                                 HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            ShippingAddressVO address = shippingAddressService.addAddress(userId, dto);
            
            log.info("新增收货地址成功，用户ID: {}, 地址ID: {}", userId, address.getId());
            return Result.success("新增收货地址成功", address);
        } catch (RuntimeException e) {
            log.warn("新增收货地址失败: {}", e.getMessage());
            return Result.error(e.getMessage());
        } catch (Exception e) {
            log.error("新增收货地址失败: {}", e.getMessage(), e);
            return Result.error("新增收货地址失败");
        }
    }

    /**
     * 更新收货地址
     */
    @PutMapping("/{id}")
    public Result<String> updateAddress(@PathVariable Long id,
                                        @Valid @RequestBody ShippingAddressDTO dto,
                                        HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean result = shippingAddressService.updateAddress(id, userId, dto);
            
            if (result) {
                log.info("更新收货地址成功，用户ID: {}, 地址ID: {}", userId, id);
                return Result.success("更新收货地址成功");
            } else {
                return Result.error("更新收货地址失败");
            }
        } catch (RuntimeException e) {
            log.warn("更新收货地址失败: {}", e.getMessage());
            return Result.error(e.getMessage());
        } catch (Exception e) {
            log.error("更新收货地址失败: {}", e.getMessage(), e);
            return Result.error("更新收货地址失败");
        }
    }

    /**
     * 删除收货地址
     */
    @DeleteMapping("/{id}")
    public Result<String> deleteAddress(@PathVariable Long id, HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean result = shippingAddressService.deleteAddress(id, userId);
            
            if (result) {
                log.info("删除收货地址成功，用户ID: {}, 地址ID: {}", userId, id);
                return Result.success("删除收货地址成功");
            } else {
                return Result.error("删除收货地址失败");
            }
        } catch (RuntimeException e) {
            log.warn("删除收货地址失败: {}", e.getMessage());
            return Result.error(e.getMessage());
        } catch (Exception e) {
            log.error("删除收货地址失败: {}", e.getMessage(), e);
            return Result.error("删除收货地址失败");
        }
    }

    /**
     * 设置为默认地址
     */
    @PutMapping("/{id}/default")
    public Result<String> setDefaultAddress(@PathVariable Long id, HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean result = shippingAddressService.setDefaultAddress(id, userId);
            
            if (result) {
                log.info("设置默认地址成功，用户ID: {}, 地址ID: {}", userId, id);
                return Result.success("设置默认地址成功");
            } else {
                return Result.error("设置默认地址失败");
            }
        } catch (RuntimeException e) {
            log.warn("设置默认地址失败: {}", e.getMessage());
            return Result.error(e.getMessage());
        } catch (Exception e) {
            log.error("设置默认地址失败: {}", e.getMessage(), e);
            return Result.error("设置默认地址失败");
        }
    }

    /**
     * 获取默认地址
     */
    @GetMapping("/default")
    public Result<ShippingAddressVO> getDefaultAddress(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            ShippingAddressVO address = shippingAddressService.getDefaultAddress(userId);
            
            if (address == null) {
                return Result.error("暂无默认地址");
            }
            
            log.info("获取默认地址成功，用户ID: {}, 地址ID: {}", userId, address.getId());
            return Result.success("获取默认地址成功", address);
        } catch (Exception e) {
            log.error("获取默认地址失败: {}", e.getMessage(), e);
            return Result.error("获取默认地址失败");
        }
    }

    /**
     * 获取收货地址数量
     */
    @GetMapping("/count")
    public Result<Integer> getAddressCount(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            int count = shippingAddressService.countUserAddresses(userId);
            
            log.info("获取收货地址数量成功，用户ID: {}, 数量: {}", userId, count);
            return Result.success("查询成功", count);
        } catch (Exception e) {
            log.error("获取收货地址数量失败: {}", e.getMessage(), e);
            return Result.error("获取收货地址数量失败");
        }
    }

    /**
     * 获取当前登录用户ID
     * 优先使用Spring Security认证，如果不可用则从HTTP Token中获取
     */
    private Long getCurrentUserId() {
        // 尝试从Spring Security获取
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.getPrincipal() != null) {
                Object principal = authentication.getPrincipal();
                if (principal instanceof UserDetails) {
                    UserDetails userDetails = (UserDetails) principal;
                    String username = userDetails.getUsername();
                    
                    com.waikuai.shop.entity.User user = userService.findByUsername(username);
                    if (user != null) {
                        return user.getId();
                    }
                }
            }
        } catch (Exception e) {
            log.debug("从Spring Security获取用户ID失败，尝试从Token获取: {}", e.getMessage());
        }
        
        // 如果Spring Security不可用，抛出异常（需要在调用处传入HttpServletRequest）
        throw new RuntimeException("用户未登录，请先登录");
    }

    /**
     * 从HTTP请求中获取用户ID（备用方案）
     */
    private Long getUserIdFromToken(HttpServletRequest request) {
        try {
            String bearerToken = request.getHeader("Authorization");
            if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
                String token = bearerToken.substring(7); // 移除 "Bearer " 前缀
                
                // 验证token格式
                if (!jwtUtil.validateTokenFormat(token)) {
                    log.warn("Token格式无效");
                    return null;
                }
                
                // 检查token是否过期
                if (jwtUtil.isTokenExpired(token)) {
                    log.warn("Token已过期");
                    return null;
                }
                
                // 从token中提取用户ID
                Long userId = jwtUtil.getUserIdFromToken(token);
                if (userId != null) {
                    log.debug("从Token中获取用户ID成功: {}", userId);
                    return userId;
                }
            }
        } catch (Exception e) {
            log.error("从Token中获取用户ID失败: {}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取当前登录用户ID（兼容多种方式）
     */
    private Long getCurrentUserId(HttpServletRequest request) {
        try {
            return getCurrentUserId();
        } catch (RuntimeException e) {
            // 如果Spring Security方式失败，尝试从Token获取
            Long userId = getUserIdFromToken(request);
            if (userId != null) {
                return userId;
            }
            // 如果都失败，抛出更明确的异常
            log.warn("获取用户ID失败: Spring Security和Token都不可用");
            throw new RuntimeException("用户未登录，请先登录");
        }
    }
}

